<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="format-detection" content="telephone=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="icon" href="/blog/blog/images/icons/favicon-16x16.png?v=2.6.2" type="image/png" sizes="16x16"><link rel="icon" href="/blog/blog/images/icons/favicon-32x32.png?v=2.6.2" type="image/png" sizes="32x32"><meta name="description" content=".back-top{position: fixed;top: 500px;height: 0px;float: right;right: 50px;} .back-top&gt;a{font-weight:bold;width: 50px;height: 50px;text-align: center;text-decoration: none;font-size: 5px;line-height:">
<meta property="og:type" content="article">
<meta property="og:title" content="VUE学习笔记-基础语法及其应用-2-深入组件开发">
<meta property="og:url" content="https://bruce-jj.gitee.io/blog/2021/04/27/VUE%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E7%9B%B8%E5%BA%94%E5%BA%94%E7%94%A8-2/index.html">
<meta property="og:site_name" content="斯人若彩虹 遇上方知有">
<meta property="og:description" content=".back-top{position: fixed;top: 500px;height: 0px;float: right;right: 50px;} .back-top&gt;a{font-weight:bold;width: 50px;height: 50px;text-align: center;text-decoration: none;font-size: 5px;line-height:">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://img-blog.csdnimg.cn/20210427202040534.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQzNDQ1MDY3,size_16,color_FFFFFF,t_70">
<meta property="article:published_time" content="2021-04-27T12:05:49.000Z">
<meta property="article:modified_time" content="2021-05-11T19:15:14.000Z">
<meta property="article:author" content="何水浪">
<meta property="article:tag" content="前端框架学习">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://img-blog.csdnimg.cn/20210427202040534.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQzNDQ1MDY3,size_16,color_FFFFFF,t_70"><title>VUE学习笔记-基础语法及其应用-2-深入组件开发 | 斯人若彩虹 遇上方知有</title><link ref="canonical" href="https://bruce-jj.gitee.io/blog/2021/04/27/VUE%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E7%9B%B8%E5%BA%94%E5%BA%94%E7%94%A8-2/"><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.12.1/css/all.min.css" type="text/css"><link rel="stylesheet" href="/blog/css/index.css?v=2.6.2"><script>var Stun = window.Stun || {};
var CONFIG = {
  root: '/blog/',
  algolia: undefined,
  assistSearch: undefined,
  fontIcon: {"prompt":{"success":"fas fa-check-circle","info":"fas fa-arrow-circle-right","warning":"fas fa-exclamation-circle","error":"fas fa-times-circle"},"copyBtn":"fas fa-copy"},
  sidebar: {"offsetTop":"20px","tocMaxDepth":6},
  header: {"enable":true,"showOnPost":true,"scrollDownIcon":false},
  postWidget: {"endText":true},
  nightMode: {"enable":true},
  back2top: {"enable":true},
  codeblock: {"style":"default","highlight":"light","wordWrap":false},
  reward: false,
  fancybox: false,
  zoomImage: {"gapAside":"20px"},
  galleryWaterfall: undefined,
  lazyload: false,
  pjax: undefined,
  externalLink: {"icon":{"enable":true,"name":"fas fa-external-link-alt"}},
  shortcuts: undefined,
  prompt: {"copyButton":"复制","copySuccess":"复制成功","copyError":"复制失败"},
  sourcePath: {"js":"js","css":"css","images":"images"},
};

window.CONFIG = CONFIG;</script><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/blog/atom.xml" title="斯人若彩虹 遇上方知有" type="application/atom+xml">
</head><body><div class="container" id="container"><header class="header" id="header"><div class="header-inner"><nav class="header-nav header-nav--fixed"><div class="header-nav-inner"><div class="header-nav-menubtn"><i class="fas fa-bars"></i></div><div class="header-nav-menu"><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/blog/"><span class="header-nav-menu-item__icon"><i class="fas fa-home"></i></span><span class="header-nav-menu-item__text">首页</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/blog/archives/"><span class="header-nav-menu-item__icon"><i class="fas fa-folder-open"></i></span><span class="header-nav-menu-item__text">归档</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/blog/categories/"><span class="header-nav-menu-item__icon"><i class="fas fa-layer-group"></i></span><span class="header-nav-menu-item__text">分类</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/blog/tags/"><span class="header-nav-menu-item__icon"><i class="fas fa-tags"></i></span><span class="header-nav-menu-item__text">标签</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/blog/friends/"><span class="header-nav-menu-item__icon"><i class="fas fa-link"></i></span><span class="header-nav-menu-item__text">友链</span></a></div></div><div class="header-nav-search"><span class="header-nav-search__icon"><i class="fas fa-search"></i></span><span class="header-nav-search__text">搜索</span></div><div class="header-nav-mode"><div class="mode"><div class="mode-track"><span class="mode-track-moon"></span><span class="mode-track-sun"></span></div><div class="mode-thumb"></div></div></div></div></nav><div class="header-banner"><div class="header-banner-info"><div class="header-banner-info__title">斯人若彩虹 遇上方知有</div><div class="header-banner-info__subtitle"></div></div></div></div></header><main class="main" id="main"><div class="main-inner"><div class="content-wrap" id="content-wrap"><div class="content" id="content"><!-- Just used to judge whether it is an article page--><div id="is-post"></div><div class="post"><header class="post-header"><h1 class="post-title">VUE学习笔记-基础语法及其应用-2-深入组件开发</h1><div class="post-meta"><span class="post-meta-item post-meta-item--createtime"><span class="post-meta-item__icon"><i class="far fa-calendar-plus"></i></span><span class="post-meta-item__info">发表于</span><span class="post-meta-item__value">2021-04-27</span></span><span class="post-meta-item post-meta-item--updatetime"><span class="post-meta-item__icon"><i class="far fa-calendar-check"></i></span><span class="post-meta-item__info">更新于</span><span class="post-meta-item__value">2021-05-12</span></span><span class="post-meta-item post-meta-item--wordcount"><span class="post-meta-item__icon"><i class="far fa-file-word"></i></span><span class="post-meta-item__info">字数统计</span><span class="post-meta-item__value">4.3k</span></span><span class="post-meta-item post-meta-item--readtime"><span class="post-meta-item__icon"><i class="far fa-clock"></i></span><span class="post-meta-item__info">阅读时长</span><span class="post-meta-item__value">31分</span></span></div></header><div class="post-body"><!-- 页面必备样式 -->
<style>
.back-top{position: fixed;top: 500px;height: 0px;float: right;right: 50px;}
.back-top>a{font-weight:bold;width: 50px;height: 50px;text-align: center;text-decoration: none;font-size: 5px;line-height: 50px;border-radius: 50px;background-color:rgba(255,255,255,0.5);}
</style>
<div class="back-top">
    <a href="#top"> >返回顶部< </a>
</div>
<!-- toc -->
<!-- 必备样式结束 -->

<p><span class="exturl"><a class="exturl__link"   target="_blank" rel="noopener" href="http://www.jspang.com/detailed?id=69" >（转）本文笔记&amp;源码地址_JS胖</a><span class="exturl__icon"><i class="fas fa-external-link-alt"></i></span></span></p>

        <h1 id="了解组件，什么是组件概念？"   >
          <a href="#了解组件，什么是组件概念？" class="heading-link"><i class="fas fa-link"></i></a><a href="#了解组件，什么是组件概念？" class="headerlink" title="了解组件，什么是组件概念？"></a>了解组件，什么是组件概念？</h1>
      <p><img   src="https://img-blog.csdnimg.cn/20210427202040534.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQzNDQ1MDY3,size_16,color_FFFFFF,t_70" style="width: image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,tepx;height: t_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQzNDQ1MDY3,size_16,color_FFFFFF,t_70px;"  alt="在这里插入图片描述"></p>
<p>从图中我们可以看到，总共的<strong>大区域分为了三个板块</strong></p>
<p><strong>上面一个Header，下面左边一个LeftSide以及右边的RightSide</strong></p>
<p>根据每个区域，又可以分为两个（最下层的绿色中间）、以及三个（最下层的绿色右边）</p>

        <h2 id="组件定义："   >
          <a href="#组件定义：" class="heading-link"><i class="fas fa-link"></i></a><a href="#组件定义：" class="headerlink" title="组件定义："></a>组件定义：</h2>
      <p><strong>所谓组件，我们就可以看成是：一个页面中的某一个Section，通过不同的组件共同拼凑</strong></p>
<p>从而，形成一个完整的组件，这也是目前前端最流行的开发方式：</p>
<p><strong>vue_component.html</strong></p>
<figure class="highlight html"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1.0&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Document<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/vue@next&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> app=Vue.createApp(&#123; &#125;)</span></span><br><span class="line"><span class="javascript">    <span class="keyword">const</span> vm=app.mount(<span class="string">&quot;#app&quot;</span>)</span></span><br><span class="line"><span class="javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></div></figure>

<p><strong>我们可以看到，现在我们将一个新的VUE实例挂载到页面ID为app的区域</strong></p>

        <h1 id="定义全局组件并使用"   >
          <a href="#定义全局组件并使用" class="heading-link"><i class="fas fa-link"></i></a><a href="#定义全局组件并使用" class="headerlink" title="定义全局组件并使用"></a>定义全局组件并使用</h1>
      <p>现在我们的app可以注册全局的组件，注册好后可以直接在根组件上进行使用</p>
<p><strong>比如我们要显示两个信息（紧接着上方的基本代码）</strong></p>
<ol>
<li><p>这是我的网站</p>
</li>
<li><p><span class="exturl"><a class="exturl__link"   target="_blank" rel="noopener" href="https://www.vincent990413.gitee.io/myblog" >https://www.vincent990413.gitee.io/myblog</a><span class="exturl__icon"><i class="fas fa-external-link-alt"></i></span></span></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第一个全局组件</span></span><br><span class="line">app.component(<span class="string">&#x27;my-component-describe&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">template</span>:<span class="string">` &lt;h1&gt; 这是我的网站 &lt;/h1&gt; `</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//第二个全局组件</span></span><br><span class="line">app.component(<span class="string">&#x27;my-component-website&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">template</span>:<span class="string">` &lt;h1&gt; https://www.vincent990413.gitee.io/myblog &lt;/h1&gt;`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></div></figure></li>
</ol>
<p><strong>以上就完成了对组件的定义，接下来我们要做的就是使用这些组件</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在创建实例的同时 使用自己的组件</span></span><br><span class="line"><span class="keyword">const</span> app = Vue.createApp(&#123;</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;my-component-describe /&gt;</span></span><br><span class="line"><span class="string">		&lt;my-component-website /&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure>

<p><strong>可以将这些步骤想象成 “初始化数据” 初始化数据之后 -&gt; 最后一步才是挂载在网页中</strong></p>

        <h2 id="全局组件的可复用性"   >
          <a href="#全局组件的可复用性" class="heading-link"><i class="fas fa-link"></i></a><a href="#全局组件的可复用性" class="headerlink" title="全局组件的可复用性"></a>全局组件的可复用性</h2>
      <p><strong>什么叫可复用性，就是可重用性，我们将一个组件封装好之后，</strong></p>
<p><strong>可以在网页中的各个区域去重复引用这个组件</strong></p>

        <h2 id="全局组件的弊端？！"   >
          <a href="#全局组件的弊端？！" class="heading-link"><i class="fas fa-link"></i></a><a href="#全局组件的弊端？！" class="headerlink" title="全局组件的弊端？！"></a>全局组件的弊端？！</h2>
      <p><strong>全局组件是有弊端的，因为你处处都可以使用，但是性能不高，应用打开就开始复杂的初始化</strong></p>

        <h1 id="局部组件"   >
          <a href="#局部组件" class="heading-link"><i class="fas fa-link"></i></a><a href="#局部组件" class="headerlink" title="局部组件"></a>局部组件</h1>
      <p><strong>针对与局部组件：我现在不注册，我要用的时候才注册这个组件，才进行使用</strong></p>
<p><strong>而全局组件是，我不用之前一直都被注册了，一直都存在在那里！</strong></p>
<p><mark>我们可以把局部组件，想象成，一个变量！我定义这个变量，我用的时候再注册它。</mark></p>

        <h2 id="创建局部组件"   >
          <a href="#创建局部组件" class="heading-link"><i class="fas fa-link"></i></a><a href="#创建局部组件" class="headerlink" title="创建局部组件"></a>创建局部组件</h2>
      <figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> myComponentCounter = &#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">count</span>: <span class="number">0</span>  </span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">` &lt;div&gt; &#123;&#123;count&#125;&#125; &lt;button @click=&quot; count++ &quot;&gt;增加1&lt;/button&gt; &lt;/div&gt; `</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></div></figure>

<p><strong>通过这种定义“变量”的方式，我们就已经定义好一个组件了，接下来我们需要在vue.CreateApp()方法里去注册</strong></p>
<p><strong>直接用component: { myComponentCounter }, 声明即可</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = Vue.CreateApp(&#123;</span><br><span class="line">	<span class="attr">components</span>: &#123;<span class="string">&#x27;my-component-counter&#x27;</span>:myComponentCounter&#125;, <span class="comment">//声明我的组件 前面的别名可以去掉</span></span><br><span class="line">	<span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;这是我的网站&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;my-component-counter/&gt; </span></span><br><span class="line"><span class="string">	`</span>	<span class="comment">//在父组件中的任何位置 都可以调用已经注册了的组件</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure>

<p><strong>我们的局部组件一般使用驼峰命名法</strong></p>
<p><strong>但多个单词，我们应该遵守规范，</strong></p>
<p><strong>1. const变量用驼峰myComponentCounter</strong></p>
<p><strong>2. 起别名时 单引号且中间加- 小写每个字母: my-component-counter</strong></p>
<p>(具体见上方代码)</p>

        <h1 id="父组件与子组件以及他们之间的静态、动态传值"   >
          <a href="#父组件与子组件以及他们之间的静态、动态传值" class="heading-link"><i class="fas fa-link"></i></a><a href="#父组件与子组件以及他们之间的静态、动态传值" class="headerlink" title="父组件与子组件以及他们之间的静态、动态传值"></a>父组件与子组件以及他们之间的静态、动态传值</h1>
      
        <h2 id="什么是父组件，什么是子组件？"   >
          <a href="#什么是父组件，什么是子组件？" class="heading-link"><i class="fas fa-link"></i></a><a href="#什么是父组件，什么是子组件？" class="headerlink" title="什么是父组件，什么是子组件？"></a>什么是父组件，什么是子组件？</h2>
      <p><mark>我们在父组件中，定义子组件并使用子组件</mark></p>
<p><strong>被注册，被使用的那个组件叫做：子组件</strong></p>
<p><strong>使用 “定义好的组件” 的组件叫做父组件</strong></p>

        <h2 id="定义全局组件Son-并在父组件中使用"   >
          <a href="#定义全局组件Son-并在父组件中使用" class="heading-link"><i class="fas fa-link"></i></a><a href="#定义全局组件Son-并在父组件中使用" class="headerlink" title="定义全局组件Son 并在父组件中使用"></a>定义全局组件Son 并在父组件中使用</h2>
      <figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">		&lt;div&gt; 这是子组件 Son div &lt;/div&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> app = Vue.CreateApp(&#123;</span><br><span class="line">	<span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;下面调用子组件&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;Son /&gt; </span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">	<span class="comment">// 调用Son 子组件</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> vm=app.mount(<span class="string">&quot;#app&quot;</span>)</span><br></pre></td></tr></table></div></figure>


        <h2 id="父组件的参数传给子组件（静态传值）"   >
          <a href="#父组件的参数传给子组件（静态传值）" class="heading-link"><i class="fas fa-link"></i></a><a href="#父组件的参数传给子组件（静态传值）" class="headerlink" title="父组件的参数传给子组件（静态传值）"></a>父组件的参数传给子组件（静态传值）</h2>
      <p><strong>所谓父组件向子组件传值，就是在调用子组件的时候，静态绑定props参数</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//父组件传入name参数 那么子组件就要有一个name处于prop数组中</span></span><br><span class="line">&lt;Son name = <span class="string">&quot;vincent&quot;</span>/&gt;</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">prop</span>:[<span class="string">&#x27;name&#x27;</span>]</span><br><span class="line">	<span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">		&lt;div&gt; 这是子组件，父组件传过来的参数name值为：&#123;&#123;name&#125;&#125; &lt;/div&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure>

<p><strong>这种方法是静态传输，一旦运行起来，就无法改变了</strong></p>

        <h2 id="父组件的参数传给子组件（动态传值）"   >
          <a href="#父组件的参数传给子组件（动态传值）" class="heading-link"><i class="fas fa-link"></i></a><a href="#父组件的参数传给子组件（动态传值）" class="headerlink" title="父组件的参数传给子组件（动态传值）"></a>父组件的参数传给子组件（动态传值）</h2>
      <p><strong>一般我们利用：将父组件中data中的参数与传入子组件的参数进行绑定</strong></p>
<p><strong>从而使得传入的值，是动态的，是可变的</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = Vue.CreateApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">name</span>: <span class="string">&#x27;Beatrix&#x27;</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;下面调用子组件&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;Son :name=&quot;name&quot; /&gt;  </span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">	<span class="comment">// 此时是动态传入给子组件的参数 </span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">prop</span>:[<span class="string">&#x27;name&#x27;</span>]</span><br><span class="line">	<span class="attr">template</span>: <span class="string">`</span></span><br><span class="line"><span class="string">		&lt;div&gt; 这是子组件，父组件传过来的参数name值为：&#123;&#123;name&#125;&#125; &lt;/div&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure>

<p><strong>这样通过修改data中的参数 完成动态绑定</strong></p>

        <h2 id="父组件的参数传给子组件（传入函数参数）"   >
          <a href="#父组件的参数传给子组件（传入函数参数）" class="heading-link"><i class="fas fa-link"></i></a><a href="#父组件的参数传给子组件（传入函数参数）" class="headerlink" title="父组件的参数传给子组件（传入函数参数）"></a>父组件的参数传给子组件（传入函数参数）</h2>
      <figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//父组件</span></span><br><span class="line"><span class="keyword">const</span> app=Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">name</span>: <span class="string">&#x27;Beatrix&#x27;</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line">		<span class="function"><span class="title">talk</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">			<span class="keyword">return</span> <span class="string">&quot;你好，我是Vincent.&quot;</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;下面调用子组件并传入函数参数talk&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;Son :talk = &quot;talk&quot; /&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//子组件</span></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>, &#123;</span><br><span class="line">	<span class="attr">props</span>:[<span class="string">&#x27;talk&#x27;</span>],</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line">		<span class="function"><span class="title">buttonTalk</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">			<span class="comment">//弹窗显示 父组件传来的函数参数</span></span><br><span class="line">			alert(<span class="built_in">this</span>.talk())</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;div&gt; 这是子组件Beatrix，我想知道你是谁？&lt;/div&gt;</span></span><br><span class="line"><span class="string">		&lt;div&gt; &lt;button @click=&quot;buttonTalk&quot;&gt;点我就知道了&lt;/button&gt; &lt;/div&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> vm=app.mount(<span class="string">&quot;#app&quot;</span>)</span><br></pre></td></tr></table></div></figure>

        <h2 id="父组件的参数传给子组件（Slot插槽）"   >
          <a href="#父组件的参数传给子组件（Slot插槽）" class="heading-link"><i class="fas fa-link"></i></a><a href="#父组件的参数传给子组件（Slot插槽）" class="headerlink" title="父组件的参数传给子组件（Slot插槽）"></a>父组件的参数传给子组件（Slot插槽）</h2>
      <p><strong>这种情况适用于，父组件传入给子组件一段HTML代码，欲在部分区域显示：</strong></p>
<ol>
<li><p>在子组件想要显示的区域，声明插槽</p>
</li>
<li><p>在父组件使用子组件的双标签形式，并插入HTML代码/其他子组件 <code>&lt;Son&gt; &lt;div&gt; &#123;&#123;counter&#125;&#125;: &lt;my-component-others /&gt;&lt;/div&gt; &lt;/Son&gt;</code> </p>
</li>
</ol>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">counter</span>:<span class="number">1</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;父组件调用子组件并传入HTML代码/其他组件&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;Son&gt; &lt;div style=&quot;background-color:red;&quot;&gt; &#123;&#123; counter &#125;&#125;&lt;/div&gt; &lt;/Son&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>, &#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line">		</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;子组件的标题&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;slot&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> vm = app.mount(<span class="string">&quot;#app&quot;</span>)</span><br></pre></td></tr></table></div></figure>

<p><mark>值得注意的是，当父组件与子组件具有同名的变量时，我们父组件传入参数时，子组件的slot中会显示父组件的属性。</mark></p>
<ul>
<li><p>父模板里调用的数据属性，使用的都是父模板里的数据。</p>
</li>
<li><p>子模板里调用的数据属性，使用的都是子模板里的数据。</p>
</li>
</ul>
<p><code>&#123;&#123;counter&#125;&#125;</code> 是在父模板中调用的，那么使用的是父模板的数据。</p>

        <h3 id="slot中的默认数据"   >
          <a href="#slot中的默认数据" class="heading-link"><i class="fas fa-link"></i></a><a href="#slot中的默认数据" class="headerlink" title="slot中的默认数据"></a>slot中的默认数据</h3>
      <p><strong>当slot中无数据传递过来是，写在slot中的数据就是默认显示数据。</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;slot&gt; 这是默认数据 &lt;/slot&gt;</span><br></pre></td></tr></table></div></figure>


        <h3 id="指定若干个插槽的位置-指定不同的name"   >
          <a href="#指定若干个插槽的位置-指定不同的name" class="heading-link"><i class="fas fa-link"></i></a><a href="#指定若干个插槽的位置-指定不同的name" class="headerlink" title="指定若干个插槽的位置(指定不同的name)"></a>指定若干个插槽的位置(指定不同的name)</h3>
      <figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;slot name=&quot;first&quot;&gt;&lt;/slot&gt; </span></span><br><span class="line"><span class="string">		&lt;div&gt;这是第二个&lt;/div&gt;</span></span><br><span class="line"><span class="string">		&lt;slot name=&quot;third&quot;&gt;&lt;/slot&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure>

<p><strong>我们可以看到，指定了name显示区域，在父组件传值的时候，也指定显示在对应name的区域即可。</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app = Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line">		</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;Son&gt;</span></span><br><span class="line"><span class="string">			&lt;template v-slot:first&gt; &lt;div&gt;这是First的参数值&lt;/div&gt; &lt;/template&gt;</span></span><br><span class="line"><span class="string">			&lt;template v-slot:third&gt; &lt;div&gt;这是third的参数值&lt;/div&gt; &lt;/template&gt;</span></span><br><span class="line"><span class="string">		&lt;/Son&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure>
<p><strong>在代码中，我们可以看到，利用 <code>v-slot:XX</code> 可以指定显示在对应子组件name为XX的区域</strong></p>
<p><mark>也可以简写成 <code>#XX</code> </mark></p>

        <h1 id="子组件"   >
          <a href="#子组件" class="heading-link"><i class="fas fa-link"></i></a><a href="#子组件" class="headerlink" title="子组件"></a>子组件</h1>
      
        <h2 id="子组件向父组件传递数据"   >
          <a href="#子组件向父组件传递数据" class="heading-link"><i class="fas fa-link"></i></a><a href="#子组件向父组件传递数据" class="headerlink" title="子组件向父组件传递数据"></a>子组件向父组件传递数据</h2>
      <ul>
<li><p>子组件调用父组件事件</p>
</li>
<li><p>子组件向父组件事件中传递参数</p>
</li>
<li><p>子组件传递参数时，如何通过<code>emits</code>进行校验</p>
</li>
</ul>
<p><strong>根据组件之间的单向数据流，子组件是没办法直接更改父组件传递过来的参数</strong></p>
<p><strong>解决办法</strong></p>
<p><strong>1. 将父组件传递过来的参数赋给子组件的数据 在子组件中更改自己的数据（本段稍后一点内容）</strong></p>
<p><strong>2. 我们可以调用父组件的 “可以改变这个参数值” 的方法，本质上是父组件来改变（紧接着读下去）</strong></p>
<p>比如：我们用父组件更改传递给子组件的counter变量（用一个方法）</p>
<p>在子组件中调用这个方法</p>
<p><strong>仔细看懂，接下来的代码！</strong></p>
<p><strong>仔细看懂，接下来的代码！</strong></p>
<p><strong>仔细看懂，接下来的代码！</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//父组件</span></span><br><span class="line"><span class="keyword">const</span> app=Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">counter</span>: <span class="number">1</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line">	  <span class="function"><span class="title">parentUpdateCounter</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		  <span class="built_in">this</span>.counter++;</span><br><span class="line">	  &#125;      </span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;下面调用子组件传入参数counter&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		</span></span><br><span class="line"><span class="string">		&lt;h1&gt;子组件通过父组件的方法，更改这个传递过去的参数（注意区分直接赋给子组件中的data参数）&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		</span></span><br><span class="line"><span class="string">		&lt;Son :counter=&quot;counter&quot; @parentUpdateCounter=&quot;parentUpdateCounter&quot;  /&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//子组件</span></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>, &#123;</span><br><span class="line">	<span class="attr">props</span>: [<span class="string">&#x27;counter&#x27;</span>],</span><br><span class="line">	<span class="attr">emits</span>:[<span class="string">&#x27;parentUpdateCounter&#x27;</span>],</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line"></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line">		<span class="function"><span class="title">childUpdate</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">			<span class="built_in">this</span>.$emit(<span class="string">&#x27;parentUpdateCounter&#x27;</span>)</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;div&gt; 这是子组件，我想看到数据变化！&lt;/div&gt;</span></span><br><span class="line"><span class="string">		&lt;div&gt; &#123;&#123; childCounter &#125;&#125;  </span></span><br><span class="line"><span class="string">		   &#123;&#123; counter &#125;&#125; &lt;button @click=&quot; childUpdate &quot;&gt;点我就知道了&lt;/button&gt;</span></span><br><span class="line"><span class="string">		 &lt;/div&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">	<span class="comment">//可以看到 上面是&#123;&#123; counter &#125;&#125; 直接引用父组件传过去的参数</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> vm=app.mount(<span class="string">&quot;#app&quot;</span>)</span><br></pre></td></tr></table></div></figure>


        <h3 id="关键代码："   >
          <a href="#关键代码：" class="heading-link"><i class="fas fa-link"></i></a><a href="#关键代码：" class="headerlink" title="关键代码："></a>关键代码：</h3>
      <p><strong>1. 首先在父组件中定义传递过去的变量counter <code>data()&#123;return&#123; counter:1 &#125;&#125;</code></strong></p>
<p><strong>2. 父组件传递过去 <code>&lt;Son :counter=&quot;counter&quot; /&gt;</code></strong></p>
<p><strong>3. 子组件中声明props用来接收 <code>props:[ &#39;counter&#39; ]</code></strong></p>
<p><strong>4. 父组件中写可以更改counter变量的方法 <code>methods:&#123;parentUpdateCounter()&#123;this.counter++&#125;&#125;</code></strong></p>
<p><strong>5. 父组件传递过去 <code>&lt;Son :counter=&quot;counter&quot; @parentUpdateCounter=&quot;parentUpdateCounter&quot;/&gt;</code> (@引用名=“父组件方法名”)</strong></p>
<p><strong>6. 子组件中声明emits用来接收 <code>emits:[&#39;parentUpdateCounter&#39;]</code>(与父组件传递过来的引用名一致)</strong></p>
<p><strong>7. 子组件在需要的时候(一般在子组件自己的方法内部)，调用这个父组件的引用名（代表对应的父组件方法）<code>this.$emit(&#39;parentUpdateCounter&#39;)</code></strong></p>

        <h2 id="子组件利用slot向父组件传递List中的数据"   >
          <a href="#子组件利用slot向父组件传递List中的数据" class="heading-link"><i class="fas fa-link"></i></a><a href="#子组件利用slot向父组件传递List中的数据" class="headerlink" title="子组件利用slot向父组件传递List中的数据"></a>子组件利用slot向父组件传递List中的数据</h2>
      <p><strong>在Javascript中的list中，我们视为对象，因此调用属性是需要 <code>obj.item</code></strong></p>
<ol>
<li>为子组件中添加list数据<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">names</span>: [<span class="string">&#x27;Vincent&#x27;</span>, <span class="string">&#x27;Beatrix&#x27;</span>, <span class="string">&#x27;James&#x27;</span>]</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;div&gt;</span></span><br><span class="line"><span class="string">			&lt;slot v-for=&quot;name in names&quot; :item=&quot;name&quot;&gt; &lt;/slot&gt;</span></span><br><span class="line"><span class="string">		&lt;/div&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure></li>
</ol>
<ul>
<li>最重要的就是我们为这个插槽，绑定了item属性，这样父组件可以调用到这个属性。</li>
</ul>
<ol start="2">
<li>父组件调用这个子组件，并得到绑定的item值<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app=Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">			&lt;Son v-slot=&quot;props&quot;&gt; </span></span><br><span class="line"><span class="string">				&lt;div&gt; &#123;&#123; props.item &#125;&#125; &lt;/div&gt;</span></span><br><span class="line"><span class="string">			&lt;/Son&gt;</span></span><br><span class="line"><span class="string">		`</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></div></figure></li>
</ol>
<ul>
<li>props可以任意取名字，但是一定是要绑定<code>item</code>这个属性</li>
</ul>

        <h1 id="校验器（引入-ElementUI）"   >
          <a href="#校验器（引入-ElementUI）" class="heading-link"><i class="fas fa-link"></i></a><a href="#校验器（引入-ElementUI）" class="headerlink" title="校验器（引入 ElementUI）"></a>校验器（引入 ElementUI）</h1>
      <p><span class="exturl"><a class="exturl__link"   target="_blank" rel="noopener" href="https://gitee.com/vincent990413/book-store-front-end" >点我，见图书管理系统的前端项目地址</a><span class="exturl__icon"><i class="fas fa-external-link-alt"></i></span></span></p>

        <h1 id="组件之间的单向数据流"   >
          <a href="#组件之间的单向数据流" class="heading-link"><i class="fas fa-link"></i></a><a href="#组件之间的单向数据流" class="headerlink" title="组件之间的单向数据流"></a>组件之间的单向数据流</h1>
      <p><strong>一句话说明，就是数据从父级组件传递给子组件，只能这样单向（从父到子）绑定</strong></p>
<p><strong>子组件内部不能直接修改从父组件传递过来的数据</strong></p>
<p><strong>比如我们在父组件中定义一个计数器counter，传给子组件后，在子组件中更改这个数据</strong></p>
<p>结论是，我们没办法看到这个数据的变化。</p>
<p><mark>既然我们没办法，直接改变父组件传过来的变量，不如我们只更改子组件data中的变量</mark></p>
<p><strong>但将这个子组件data中的变量 赋值为父组件传过来的变量</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">比如父组件传过来的变量为counter</span><br><span class="line"></span><br><span class="line"><span class="comment">//父组件</span></span><br><span class="line"><span class="keyword">const</span> app=Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">counter</span>: <span class="number">1</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">methods</span>:&#123;</span><br><span class="line"></span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt;下面调用子组件并静态传入函数参数talk&lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;Son :counter = &quot;counter&quot; /&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">//子组件中</span></span><br><span class="line">app.component(<span class="string">&#x27;myComponentCounter&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">props</span>: [<span class="string">&#x27;counter&#x27;</span>],</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="comment">//关键一步，我们赋给可以改变的childCounter</span></span><br><span class="line">			<span class="attr">childCounter</span>: <span class="built_in">this</span>.counter</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&#123;&#123; childCounter &#125;&#125; &lt;button @click=&quot; childCounter++ &quot;&gt; 点我可以看到数据的变化 &lt;/button&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></div></figure>

<p><strong>这样我们就可以看到数据的变化了！</strong></p>
<ul>
<li>思考，为什么要有单向数据流的概念呢？</li>
<li>因为，如果父组件使用多个相同的子组件，传入不同的参数，我们希望这些子组件互不干扰。</li>
</ul>
<p><strong>也就是说，子组件不能直接更改父组件的数据，而是更改自己的数据。</strong></p>

        <h1 id="异步组件和Promise讲解"   >
          <a href="#异步组件和Promise讲解" class="heading-link"><i class="fas fa-link"></i></a><a href="#异步组件和Promise讲解" class="headerlink" title="异步组件和Promise讲解"></a>异步组件和Promise讲解</h1>
      
        <h2 id="异步的概念"   >
          <a href="#异步的概念" class="heading-link"><i class="fas fa-link"></i></a><a href="#异步的概念" class="headerlink" title="异步的概念"></a>异步的概念</h2>
      <p><strong>所谓异步，就是几个操作不是按严格的顺序执行（真正的执行顺序未知）</strong></p>
<p><strong>与它相反的概念是同步：</strong></p>
<ul>
<li>举个例子，如何将大象塞到冰箱里？</li>
</ul>
<ol>
<li><p>打开冰箱</p>
</li>
<li><p>将大象塞进去</p>
</li>
<li><p>关掉冰箱门</p>
</li>
</ol>
<p>以上的操作就是同步的，具有严格的前后时序。</p>
<p><em>一般而言，我们将经常要去后台请求数据的业务/组件，封装成异步的。</em></p>

        <h2 id="Promise"   >
          <a href="#Promise" class="heading-link"><i class="fas fa-link"></i></a><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h2>
      <figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">app.component(<span class="string">&#x27;async-component&#x27;</span>,Vue.defineAsyncComponent(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve,reject</span>)=&gt;</span>&#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">            resolve(&#123;</span><br><span class="line">                <span class="attr">template</span>:<span class="string">`&lt;div&gt;这是一个异步组件&lt;/div&gt;`</span></span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;,<span class="number">3000</span>)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;))</span><br></pre></td></tr></table></div></figure>

<p><strong>我们在调用这个组件时，三秒钟后，会出现对应组件中的内容</strong></p>
<ul>
<li>关于Promise的概念，详情<span class="exturl"><a class="exturl__link"   target="_blank" rel="noopener" href="https://vincent990413.gitee.io/myblog/2021/03/15/JavaScript/#promise-%E7%B1%BB%E8%A7%A3%E5%86%B3%E5%89%8D%E7%AB%AF%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8%E5%90%8E%E5%8F%B0%E6%95%B0%E6%8D%AE" >点我去JavaSCript基础教程</a><span class="exturl__icon"><i class="fas fa-external-link-alt"></i></span></span></li>
</ul>

        <h1 id="爷孙级别组件数据传递（多用于多级组件）"   >
          <a href="#爷孙级别组件数据传递（多用于多级组件）" class="heading-link"><i class="fas fa-link"></i></a><a href="#爷孙级别组件数据传递（多用于多级组件）" class="headerlink" title="爷孙级别组件数据传递（多用于多级组件）"></a>爷孙级别组件数据传递（多用于多级组件）</h1>
      
        <h2 id="顺序依次继承数据"   >
          <a href="#顺序依次继承数据" class="heading-link"><i class="fas fa-link"></i></a><a href="#顺序依次继承数据" class="headerlink" title="顺序依次继承数据"></a>顺序依次继承数据</h2>
      <p><strong>如果有一个爷爷，他现在有一套房子（北京四合院），想过继下去。</strong></p>
<p>我们就可以实现：</p>
<ol>
<li>从爷爷过继给父亲，再从父亲过继给孙子 props参数<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app=Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">house</span>: <span class="string">&#x27;北京四合院，价值8000万！&#x27;</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h1&gt; 这是爷爷，爷爷过继给儿子！ &lt;/h1&gt;</span></span><br><span class="line"><span class="string">		&lt;Son :house=&quot;house&quot; /&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">props</span>:[<span class="string">&#x27;house&#x27;</span>],</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h2&gt;儿子接受房子，这个房子是： &#123;&#123; house &#125;&#125; &lt;h2&gt;</span></span><br><span class="line"><span class="string">		&lt;h2&gt;儿子继续过继给孙子&lt;/h2&gt;</span></span><br><span class="line"><span class="string">		&lt;Grandson :house=&quot;house&quot; /&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Grandson&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">props</span>:[<span class="string">&#x27;house&#x27;</span>],</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h3&gt;这是孙子，接受房子，房子信息是： &#123;&#123;house&#125;&#125; &lt;/h3&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> vm=app.mount(<span class="string">&quot;#app&quot;</span>)</span><br></pre></td></tr></table></div></figure></li>
</ol>
<p><strong>这样通过依次继承的方法，的确可以做到将“爷爷”级别的组件数据传递给“孙子”组件</strong></p>
<p><em>但如果项目中出现5，6次继承层次的孙孙孙…这样代码就太冗余了</em></p>

        <h2 id="指定组件层次接受参数-Provide-amp-Inject"   >
          <a href="#指定组件层次接受参数-Provide-amp-Inject" class="heading-link"><i class="fas fa-link"></i></a><a href="#指定组件层次接受参数-Provide-amp-Inject" class="headerlink" title="指定组件层次接受参数 Provide&amp;Inject"></a>指定组件层次接受参数 Provide&amp;Inject</h2>
      <p><strong>Provide意为提供参数，Inject引入接受、注入参数</strong></p>
<p><strong>也就是说，我们在“祖先”级别的组件提供某个参数，可以跳过中间的若干个组件，直接过继给指定的组件</strong></p>
<figure class="highlight js"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> app=Vue.createApp(&#123;</span><br><span class="line">	<span class="function"><span class="title">data</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">		<span class="keyword">return</span>&#123;</span><br><span class="line">			<span class="attr">house</span>: <span class="string">&#x27;北京四合院，价值8000万！&#x27;</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">provide</span>:&#123;</span><br><span class="line">		<span class="attr">houseDirectlyToGrandson</span>: <span class="string">&#x27;给孙子的海景房！&#x27;</span></span><br><span class="line">	&#125;,</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">			&lt;h1&gt; 这是爷爷，爷爷不过继给儿子，直接给孙子！ &lt;/h1&gt;</span></span><br><span class="line"><span class="string">			&lt;Son/&gt;</span></span><br><span class="line"><span class="string">		`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Son&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">props</span>:[<span class="string">&#x27;house&#x27;</span>],</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h2&gt;这是儿子，不接受参数，不传递参数！&lt;/h2&gt;</span></span><br><span class="line"><span class="string">		&lt;Grandson/&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.component(<span class="string">&#x27;Grandson&#x27;</span>,&#123;</span><br><span class="line">	<span class="attr">props</span>:[<span class="string">&#x27;house&#x27;</span>],</span><br><span class="line">	<span class="attr">inject</span>:[<span class="string">&#x27;houseDirectlyToGrandson&#x27;</span>],</span><br><span class="line">	<span class="attr">template</span>:<span class="string">`</span></span><br><span class="line"><span class="string">		&lt;h3&gt;这是孙子，接受房子，房子信息是： &#123;&#123;houseDirectlyToGrandson&#125;&#125; &lt;/h3&gt;</span></span><br><span class="line"><span class="string">	`</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> vm=app.mount(<span class="string">&quot;#app&quot;</span>)</span><br></pre></td></tr></table></div></figure>

<p><strong>关键代码：</strong></p>
<ol>
<li><p>在爷爷组件中，提供属性 <code>provide:&#123; newHounse:&#39;新房子&#39; &#125;</code></p>
</li>
<li><p>在任意后代组件中，提供注入参数：<code>inject:[&#39;newHouse&#39;]</code> 即可引用</p>
</li>
</ol>
<ul>
<li><p>如果这种层级关系达到5-6级，再使用props进行传递，那就会非常麻烦，而且会有大量的代码冗余。</p>
</li>
<li><p>使用provide和inject可以解决这个问题。</p>
</li>
</ul>
</div><footer class="post-footer"><div class="post-ending ending"><div class="ending__text">------ 本文结束，感谢您的阅读 ------</div></div><div class="post-copyright copyright"><div class="copyright-author"><span class="copyright-author__name">本文作者: </span><span class="copyright-author__value"><a href="https://bruce-jj.gitee.io/blog">何水浪</a></span></div><div class="copyright-link"><span class="copyright-link__name">本文链接: </span><span class="copyright-link__value"><a href="https://bruce-jj.gitee.io/blog/2021/04/27/VUE%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E7%9B%B8%E5%BA%94%E5%BA%94%E7%94%A8-2/">https://bruce-jj.gitee.io/blog/2021/04/27/VUE%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95%E5%8F%8A%E7%9B%B8%E5%BA%94%E5%BA%94%E7%94%A8-2/</a></span></div><div class="copyright-notice"><span class="copyright-notice__name">版权声明: </span><span class="copyright-notice__value">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en" rel="external nofollow" target="_blank">BY-NC-SA</a> 许可协议。转载请注明出处！</span></div></div><div class="post-tags"><span class="post-tags-item"><span class="post-tags-item__icon"><i class="fas fa-tag"></i></span><a class="post-tags-item__link" href="https://bruce-jj.gitee.io/blog/tags/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E5%AD%A6%E4%B9%A0/">前端框架学习</a></span></div><nav class="post-paginator paginator"><div class="paginator-prev"><a class="paginator-prev__link" href="/blog/2021/05/04/%E5%9F%BA%E4%BA%8EVUE-Firebase%E5%9C%A8%E7%BA%BF%E8%81%8A%E5%A4%A9%E5%AE%A4APP/"><span class="paginator-prev__icon"><i class="fas fa-angle-left"></i></span><span class="paginator-prev__text">基于VUE&amp;Firebase的在线聊天室APP</span></a></div><div class="paginator-next"><a class="paginator-next__link" href="/blog/2021/04/15/Java%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"><span class="paginator-prev__text">Java反射机制-学习笔记</span><span class="paginator-next__icon"><i class="fas fa-angle-right"></i></span></a></div></nav></footer></div></div><div class="comments" id="comments"><div id="valine-container"></div></div></div><div class="sidebar-wrap" id="sidebar-wrap"><aside class="sidebar" id="sidebar"><div class="sidebar-nav"><span class="sidebar-nav-toc current">文章目录</span><span class="sidebar-nav-ov">站点概览</span></div><section class="sidebar-toc"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%BA%86%E8%A7%A3%E7%BB%84%E4%BB%B6%EF%BC%8C%E4%BB%80%E4%B9%88%E6%98%AF%E7%BB%84%E4%BB%B6%E6%A6%82%E5%BF%B5%EF%BC%9F"><span class="toc-number">1.</span> <span class="toc-text">
          了解组件，什么是组件概念？</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E5%AE%9A%E4%B9%89%EF%BC%9A"><span class="toc-number">1.1.</span> <span class="toc-text">
          组件定义：</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%AE%9A%E4%B9%89%E5%85%A8%E5%B1%80%E7%BB%84%E4%BB%B6%E5%B9%B6%E4%BD%BF%E7%94%A8"><span class="toc-number">2.</span> <span class="toc-text">
          定义全局组件并使用</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%A8%E5%B1%80%E7%BB%84%E4%BB%B6%E7%9A%84%E5%8F%AF%E5%A4%8D%E7%94%A8%E6%80%A7"><span class="toc-number">2.1.</span> <span class="toc-text">
          全局组件的可复用性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%A8%E5%B1%80%E7%BB%84%E4%BB%B6%E7%9A%84%E5%BC%8A%E7%AB%AF%EF%BC%9F%EF%BC%81"><span class="toc-number">2.2.</span> <span class="toc-text">
          全局组件的弊端？！</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%B1%80%E9%83%A8%E7%BB%84%E4%BB%B6"><span class="toc-number">3.</span> <span class="toc-text">
          局部组件</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E5%B1%80%E9%83%A8%E7%BB%84%E4%BB%B6"><span class="toc-number">3.1.</span> <span class="toc-text">
          创建局部组件</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%88%B6%E7%BB%84%E4%BB%B6%E4%B8%8E%E5%AD%90%E7%BB%84%E4%BB%B6%E4%BB%A5%E5%8F%8A%E4%BB%96%E4%BB%AC%E4%B9%8B%E9%97%B4%E7%9A%84%E9%9D%99%E6%80%81%E3%80%81%E5%8A%A8%E6%80%81%E4%BC%A0%E5%80%BC"><span class="toc-number">4.</span> <span class="toc-text">
          父组件与子组件以及他们之间的静态、动态传值</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E7%88%B6%E7%BB%84%E4%BB%B6%EF%BC%8C%E4%BB%80%E4%B9%88%E6%98%AF%E5%AD%90%E7%BB%84%E4%BB%B6%EF%BC%9F"><span class="toc-number">4.1.</span> <span class="toc-text">
          什么是父组件，什么是子组件？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%9A%E4%B9%89%E5%85%A8%E5%B1%80%E7%BB%84%E4%BB%B6Son-%E5%B9%B6%E5%9C%A8%E7%88%B6%E7%BB%84%E4%BB%B6%E4%B8%AD%E4%BD%BF%E7%94%A8"><span class="toc-number">4.2.</span> <span class="toc-text">
          定义全局组件Son 并在父组件中使用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E5%8F%82%E6%95%B0%E4%BC%A0%E7%BB%99%E5%AD%90%E7%BB%84%E4%BB%B6%EF%BC%88%E9%9D%99%E6%80%81%E4%BC%A0%E5%80%BC%EF%BC%89"><span class="toc-number">4.3.</span> <span class="toc-text">
          父组件的参数传给子组件（静态传值）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E5%8F%82%E6%95%B0%E4%BC%A0%E7%BB%99%E5%AD%90%E7%BB%84%E4%BB%B6%EF%BC%88%E5%8A%A8%E6%80%81%E4%BC%A0%E5%80%BC%EF%BC%89"><span class="toc-number">4.4.</span> <span class="toc-text">
          父组件的参数传给子组件（动态传值）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E5%8F%82%E6%95%B0%E4%BC%A0%E7%BB%99%E5%AD%90%E7%BB%84%E4%BB%B6%EF%BC%88%E4%BC%A0%E5%85%A5%E5%87%BD%E6%95%B0%E5%8F%82%E6%95%B0%EF%BC%89"><span class="toc-number">4.5.</span> <span class="toc-text">
          父组件的参数传给子组件（传入函数参数）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%88%B6%E7%BB%84%E4%BB%B6%E7%9A%84%E5%8F%82%E6%95%B0%E4%BC%A0%E7%BB%99%E5%AD%90%E7%BB%84%E4%BB%B6%EF%BC%88Slot%E6%8F%92%E6%A7%BD%EF%BC%89"><span class="toc-number">4.6.</span> <span class="toc-text">
          父组件的参数传给子组件（Slot插槽）</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#slot%E4%B8%AD%E7%9A%84%E9%BB%98%E8%AE%A4%E6%95%B0%E6%8D%AE"><span class="toc-number">4.6.1.</span> <span class="toc-text">
          slot中的默认数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8C%87%E5%AE%9A%E8%8B%A5%E5%B9%B2%E4%B8%AA%E6%8F%92%E6%A7%BD%E7%9A%84%E4%BD%8D%E7%BD%AE-%E6%8C%87%E5%AE%9A%E4%B8%8D%E5%90%8C%E7%9A%84name"><span class="toc-number">4.6.2.</span> <span class="toc-text">
          指定若干个插槽的位置(指定不同的name)</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%AD%90%E7%BB%84%E4%BB%B6"><span class="toc-number">5.</span> <span class="toc-text">
          子组件</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AD%90%E7%BB%84%E4%BB%B6%E5%90%91%E7%88%B6%E7%BB%84%E4%BB%B6%E4%BC%A0%E9%80%92%E6%95%B0%E6%8D%AE"><span class="toc-number">5.1.</span> <span class="toc-text">
          子组件向父组件传递数据</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%B3%E9%94%AE%E4%BB%A3%E7%A0%81%EF%BC%9A"><span class="toc-number">5.1.1.</span> <span class="toc-text">
          关键代码：</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AD%90%E7%BB%84%E4%BB%B6%E5%88%A9%E7%94%A8slot%E5%90%91%E7%88%B6%E7%BB%84%E4%BB%B6%E4%BC%A0%E9%80%92List%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE"><span class="toc-number">5.2.</span> <span class="toc-text">
          子组件利用slot向父组件传递List中的数据</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%A0%A1%E9%AA%8C%E5%99%A8%EF%BC%88%E5%BC%95%E5%85%A5-ElementUI%EF%BC%89"><span class="toc-number">6.</span> <span class="toc-text">
          校验器（引入 ElementUI）</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E4%B9%8B%E9%97%B4%E7%9A%84%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81"><span class="toc-number">7.</span> <span class="toc-text">
          组件之间的单向数据流</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5%E7%BB%84%E4%BB%B6%E5%92%8CPromise%E8%AE%B2%E8%A7%A3"><span class="toc-number">8.</span> <span class="toc-text">
          异步组件和Promise讲解</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5%E7%9A%84%E6%A6%82%E5%BF%B5"><span class="toc-number">8.1.</span> <span class="toc-text">
          异步的概念</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Promise"><span class="toc-number">8.2.</span> <span class="toc-text">
          Promise</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%88%B7%E5%AD%99%E7%BA%A7%E5%88%AB%E7%BB%84%E4%BB%B6%E6%95%B0%E6%8D%AE%E4%BC%A0%E9%80%92%EF%BC%88%E5%A4%9A%E7%94%A8%E4%BA%8E%E5%A4%9A%E7%BA%A7%E7%BB%84%E4%BB%B6%EF%BC%89"><span class="toc-number">9.</span> <span class="toc-text">
          爷孙级别组件数据传递（多用于多级组件）</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%A1%BA%E5%BA%8F%E4%BE%9D%E6%AC%A1%E7%BB%A7%E6%89%BF%E6%95%B0%E6%8D%AE"><span class="toc-number">9.1.</span> <span class="toc-text">
          顺序依次继承数据</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%8C%87%E5%AE%9A%E7%BB%84%E4%BB%B6%E5%B1%82%E6%AC%A1%E6%8E%A5%E5%8F%97%E5%8F%82%E6%95%B0-Provide-amp-Inject"><span class="toc-number">9.2.</span> <span class="toc-text">
          指定组件层次接受参数 Provide&amp;Inject</span></a></li></ol></li></ol></section><!-- ov = overview--><section class="sidebar-ov hide"><div class="sidebar-ov-author"><div class="sidebar-ov-author__avatar"><img class="sidebar-ov-author__avatar_img" src="/blog/images/avatar.jpg" alt="avatar"></div><p class="sidebar-ov-author__text">C'est la vie</p></div><div class="sidebar-ov-state"><a class="sidebar-ov-state-item sidebar-ov-state-item--posts" href="/blog/archives/"><div class="sidebar-ov-state-item__count">48</div><div class="sidebar-ov-state-item__name">归档</div></a><a class="sidebar-ov-state-item sidebar-ov-state-item--categories" href="/blog/categories/"><div class="sidebar-ov-state-item__count">19</div><div class="sidebar-ov-state-item__name">分类</div></a><a class="sidebar-ov-state-item sidebar-ov-state-item--tags" href="/blog/tags/"><div class="sidebar-ov-state-item__count">20</div><div class="sidebar-ov-state-item__name">标签</div></a></div><div class="sidebar-ov-cc"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en" target="_blank" rel="noopener" data-popover="知识共享许可协议" data-popover-pos="up"><img src="/blog/images/cc-by-nc-sa.svg"></a></div></section><div class="sidebar-reading"><div class="sidebar-reading-info"><span class="sidebar-reading-info__text">你已阅读了 </span><span class="sidebar-reading-info__num">0</span><span class="sidebar-reading-info__perc">%</span></div><div class="sidebar-reading-line"></div></div></aside></div><div class="clearfix"></div></div></main><footer class="footer" id="footer"><div class="footer-inner"><div><span>Copyright © 2021</span><span class="footer__icon"><i class="fas fa-heart"></i></span><span>何水浪</span></div><div><span>由 <a href="http://hexo.io/" title="Hexo" target="_blank" rel="noopener">Hexo</a> 强力驱动</span><span> v5.4.0</span><span class="footer__devider">|</span><span>主题 - <a href="https://github.com/liuyib/hexo-theme-stun/" title="Stun" target="_blank" rel="noopener">Stun</a></span><span> v2.6.2</span></div></div></footer><div class="loading-bar" id="loading-bar"><div class="loading-bar__progress"></div></div><div class="back2top" id="back2top"><span class="back2top__icon"><i class="fas fa-rocket"></i></span></div></div><div class="search-mask"></div><div class="search-popup"><span class="search-close"></span><div class="search-input"><input placeholder="搜索文章（支持多关键词，请用空格分隔）"></div><div class="search-results"></div></div><script src="https://cdn.jsdelivr.net/npm/jquery@v3.4.1/dist/jquery.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.2/velocity.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.2/velocity.ui.min.js"></script><script>function initSearch() {
  var isXML = true;
  var search_path = 'search.json';

  if (!search_path) {
    search_path = 'search.xml';
  } else if (/json$/i.test(search_path)) {
    isXML = false;
  }

  var path = '/blog/' + search_path;
  $.ajax({
    url: path,
    dataType: isXML ? 'xml' : 'json',
    async: true,
    success: function (res) {
      var datas = isXML ? $('entry', res).map(function () {
        // 将 XML 转为 JSON
        return {
          title: $('title', this).text(),
          content: $('content', this).text(),
          url: $('url', this).text()
        };
      }).get() : res;
      var $input = $('.search-input input');
      var $result = $('.search-results');
      // 搜索对象（标题、内容）的权重，影响显示顺序
      var WEIGHT = { title: 100, content: 1 };
      var searchPost = function () {
        var searchText = $input.val().toLowerCase().trim();
        // 根据空白字符分隔关键字
        var keywords = searchText.split(/[\s]+/);
        // 搜索结果
        var matchPosts = [];

        // 有多个关键字时，将原文字整个保存下来
        if (keywords.length > 1) {
          keywords.push(searchText);
        }
        // 防止未输入字符时搜索
        if (searchText.length > 0) {
          datas.forEach(function (data) {
            var isMatch  = false;
            // 没有标题的文章使用预设的 i18n 变量代替
            var title = (data.title && data.title.trim()) || '[ 文章无标题 ]';
            var titleLower = title && title.toLowerCase();
            // 删除 HTML 标签 和 所有空白字符
            var content = data.content && data.content.replace(/<[^>]+>/g, '');
            var contentLower = content && content.toLowerCase();
            // 删除重复的 /
            var postURL = data.url && decodeURI(data.url).replace(/\/{2,}/g, '/');
            // 标题中匹配到的关键词
            var titleHitSlice = [];
            // 内容中匹配到的关键词
            var contentHitSlice = [];

            keywords.forEach(function (keyword) {
              /**
              * 获取匹配的关键词的索引
              * @param {String} keyword 要匹配的关键字
              * @param {String} text 原文字
              * @param {Boolean} caseSensitive 是否区分大小写
              * @param {Number} weight 匹配对象的权重。权重大的优先显示
              * @return {Array}
              */
              function getIndexByword (word, text, caseSensitive, weight) {
                if (!word || !text) {
                  return [];
                };

                var startIndex = 0; // 每次匹配的开始索引
                var index = -1;     // 匹配到的索引值
                var result = [];    // 匹配结果

                if (!caseSensitive) {
                  word = word.toLowerCase();
                  text = text.toLowerCase();
                }

                while((index = text.indexOf(word, startIndex)) !== -1) {
                  var hasMatch = false;
                  // 索引位置相同的关键词，保留长度较长的
                  titleHitSlice.forEach(function (hit) {
                    if (hit.index === index && hit.word.length < word.length) {
                      hit.word = word;
                      hasMatch = true;
                    }
                  });
                  startIndex = index + word.length;
                  !hasMatch && result.push({ index: index, word: word, weight: weight });
                }
                return result;
              }
              titleHitSlice = titleHitSlice.concat(getIndexByword(keyword, titleLower, false, WEIGHT.title));
              contentHitSlice = contentHitSlice.concat(getIndexByword(keyword, contentLower, false, WEIGHT.content));
            });

            var hitTitle = titleHitSlice.length;
            var hitContent = contentHitSlice.length;

            if (hitTitle > 0 || hitContent > 0) {
              isMatch = true;
            }
            if (isMatch) {
              ;[titleHitSlice, contentHitSlice].forEach(function (hit) {
                // 按照匹配文字的索引的递增顺序排序
                hit.sort(function (left, right) {
                  return left.index - right.index;
                });
              });
              /**
              * 给文本中匹配到的关键词添加标记，从而进行高亮显示
              * @param {String} text 原文本
              * @param {Array} hitSlice 匹配项的索引信息
              * @param {Number} start 开始索引
              * @param {Number} end 结束索引
              * @return {String}
              */
              function highlightKeyword (text, hitSlice, start, end) {
                if (!text || !hitSlice || !hitSlice.length) {
                  return;
                }

                var result = '';
                var startIndex = start;
                var endIndex = end;
                hitSlice.forEach(function (hit) {
                  if (hit.index < startIndex) {
                    return;
                  }

                  var hitWordEnd = hit.index + hit.word.length;
                  result += text.slice(startIndex, hit.index);
                  result += '<b>' + text.slice(hit.index, hitWordEnd) + '</b>';
                  startIndex = hitWordEnd;
                });
                result += text.slice(startIndex, endIndex);
                return result;
              }

              var postData = {};
              // 文章总的搜索权重
              var postWeight = titleHitSlice.length * WEIGHT.title + contentHitSlice.length * WEIGHT.content;
              // 标记匹配关键词后的标题
              var postTitle = highlightKeyword(title, titleHitSlice, 0, title.length) || title;
              // 标记匹配关键词后的内容
              var postContent;
              // 显示内容的长度
              var SHOW_WORD_LENGTH = 200;
              // 命中关键词前的字符显示长度
              var SHOW_WORD_FRONT_LENGTH = 20;
              var SHOW_WORD_END_LENGTH = SHOW_WORD_LENGTH - SHOW_WORD_FRONT_LENGTH;

              // 截取匹配的第一个字符，前后共 200 个字符来显示
              if (contentHitSlice.length > 0) {
                var firstIndex = contentHitSlice[0].index;
                var start = firstIndex > SHOW_WORD_FRONT_LENGTH ? firstIndex - SHOW_WORD_FRONT_LENGTH : 0;
                var end = firstIndex + SHOW_WORD_END_LENGTH;
                postContent = highlightKeyword(content, contentHitSlice, start, end);
              } else { // 未匹配到内容，直接截取前 200 个字符来显示
                postContent = content.slice(0, SHOW_WORD_LENGTH);
              }
              postData.title = postTitle;
              postData.content = postContent;
              postData.url = postURL;
              postData.weight = postWeight;
              matchPosts.push(postData);
            }
          });
        }

        var resultInnerHtml = '';
        if (matchPosts.length) {
          // 按权重递增的顺序排序，使权重大的优先显示
          matchPosts.sort(function (left, right) {
            return right.weight - left.weight;
          });
          resultInnerHtml += '<ul>';
          matchPosts.forEach(function (post) {
            resultInnerHtml += '<li><a class="search-results-title" href="' + post.url + '">';
            resultInnerHtml += post.title;
            resultInnerHtml += '</a><div class="search-results-content">';
            resultInnerHtml += post.content;
            resultInnerHtml += '</div></li>';
          });
          resultInnerHtml += '</ul>';
        } else {
          resultInnerHtml += '<div class="search-results-none"><i class="far fa-meh"></i></div>';
        }
        $result.html(resultInnerHtml);
      };
      $input.on('input', searchPost);
      $input.on('keyup', function (e) {
        if (e.keyCode === Stun.utils.codeToKeyCode('Enter')) {
          searchPost();
        }
      });
    }
  });
}

function closeSearch () {
  $('body').css({ overflow: 'auto' });
  $('.search-popup').css({ display: 'none' });
  $('.search-mask').css({ display: 'none' });
}

window.addEventListener('DOMContentLoaded', function () {
  Stun.utils.pjaxReloadLocalSearch = function () {
    $('.header-nav-search').on('click', function (e) {
      e.stopPropagation();
      $('body').css('overflow', 'hidden');
      $('.search-popup')
        .velocity('stop')
        .velocity('transition.expandIn', {
          duration: 300,
          complete: function () {
            $('.search-popup input').focus();
          }
        });
      $('.search-mask')
        .velocity('stop')
        .velocity('transition.fadeIn', {
          duration: 300
        });

      initSearch();
    });
    $('.search-mask, .search-close').on('click', function () {
      closeSearch();
    });
    $(document).on('keydown', function (e) {
      // Escape <=> 27
      if (e.keyCode === Stun.utils.codeToKeyCode('Escape')) {
        closeSearch();
      }
    });
  };

  Stun.utils.pjaxReloadLocalSearch();
}, false);

function safeOpenUrl(url) {
  var newTab = window.open();
  newTab.opener = null;
  newTab.location = url;
}

function extSearch(engine) {
  var engines = {
    google: 'https://www.google.com/search?q=',
    bing: 'https://cn.bing.com/search?q=',
    baidu: 'https://www.baidu.com/s?ie=UTF-8&wd=',
  };
  var host = window.location.host;
  var query = $('.search-input input').val().toLowerCase().trim();
  var uri = engines[engine] + query + ' site:' + host;

  if (query) {
    safeOpenUrl(uri);
  } else {
    Stun.utils.popAlert('warning', '请输入字符');
  }
}

var assistSearchList = window.CONFIG.assistSearch;

if (Array.isArray(assistSearchList)) {
  assistSearchList.forEach(function (name) {
    document.querySelector('.search-btns-item--' + name).addEventListener('click', function () {
      extSearch(name);
    }, false);
  });
}</script><script src="https://cdn.jsdelivr.net/npm/leancloud-storage@latest/dist/av-min.js"></script><script src="https://cdn.jsdelivr.net/npm/valine@latest/dist/Valine.min.js"></script><script>function loadValine () {
  var GUEST_INFO = ['nick', 'mail', 'link'];
  var guest_info = 'nick';

  guest_info = guest_info.split(',').filter(function(item) {
    return GUEST_INFO.indexOf(item) > -1;
  });
  new Valine({
    el: '#valine-container',
    appId: 'fJ4fFnieffDVKy4Jkn16aHdO-gzGzoHsz',
    appKey: 'qfVo2CUC2pJ3udFzLFnd0GBM',
    notify: true,
    verify: true,
    placeholder: '说点啥再走呗~爱你',
    avatar: 'mp',
    meta: guest_info,
    pageSize: '10' || 10,
    visitor: false,
    recordIP: false,
    lang: '' || 'zh-cn',
    path: window.location.pathname
  });
}

if (false) {
  loadValine();
} else {
  window.addEventListener('DOMContentLoaded', loadValine, false);
}</script><script src="/blog/js/utils.js?v=2.6.2"></script><script src="/blog/js/stun-boot.js?v=2.6.2"></script><script src="/blog/js/scroll.js?v=2.6.2"></script><script src="/blog/js/header.js?v=2.6.2"></script><script src="/blog/js/sidebar.js?v=2.6.2"></script><script type="application/json" src="/blog/search.json"></script></body></html>